package gzip

import (
	"archive/tar"
	"compress/gzip"
	"io"
	"os"
	"path/filepath"
)

// 解压 tar.gz
func DeCompress(tarFile, path string) error {
	srcFile, err := os.Open(tarFile)
	if err != nil {
		return err
	}
	defer srcFile.Close()
	gr, err := gzip.NewReader(srcFile)
	if err != nil {
		return err
	}
	defer gr.Close()
	tr := tar.NewReader(gr)
	for {
		hdr, err := tr.Next()
		if err != nil {
			if err == io.EOF {
				break
			} else {
				return err
			}
		}
		filename := filepath.Join(path, hdr.Name)
		file, err := createFile(filename)
		if err != nil {
			return err
		}
		io.Copy(file, tr)
	}
	return nil
}

// 创建文件
func createFile(name string) (*os.File, error) {
	// err := os.MkdirAll(string([]rune(name)[0:strings.LastIndex(name, "/")]), 0666)
	rs := []rune(name)
	p := -1
	for i := len(rs); i > 0; i-- {
		if rs[i-1] == filepath.Separator {
			p = i - 1
			break
		}
	}
	if p > -1 {
		err := os.MkdirAll(string([]rune(name)[0:p]), 0766)
		if err != nil && err != os.ErrExist {
			return nil, err
		}
	}
	return os.Create(name)
}

// 压缩 使用gzip压缩成tar.gz
func Compress(files []*os.File, dest string) error {
	d, err := os.Create(dest)
	if err != nil {
		return nil
	}
	defer d.Close()
	gw := gzip.NewWriter(d)
	defer gw.Close()
	tw := tar.NewWriter(gw)
	defer tw.Close()
	for _, file := range files {
		err := compress(file, "", tw)
		if err != nil {
			return err
		}
	}
	return nil
}

// 压缩文件
func compress(file *os.File, prefix string, tw *tar.Writer) error {
	info, err := file.Stat()
	if err != nil {
		return err
	}
	if info.IsDir() {
		if len(prefix) > 0 {
			// prefix = filepath.Join(prefix, info.Name()) // windows压缩是目录分割符是 '\',tau不解析这个符合，
			prefix = prefix + "/" + info.Name() // 压缩文件使用 '/' 固定格式，tau才可以解析
		} else {
			prefix = info.Name()
		}

		fileInfos, err := file.Readdir(-1)

		if err != nil {
			return err
		}
		for _, fi := range fileInfos {
			f, err := os.Open(filepath.Join(file.Name(), fi.Name()))
			if err != nil {
				return err
			}
			err = compress(f, prefix, tw)
			if err != nil {
				return err
			}
		}
	} else {
		header, err := tar.FileInfoHeader(info, "")
		if len(prefix) > 0 {
			// header.Name = filepath.Join(prefix, header.Name) // windows压缩是目录分割符是 '\',tau不解析这个符合，
			header.Name = prefix + "/" + header.Name // 压缩文件使用 '/' 固定格式，tau才可以解析
		}

		if err != nil {
			return err
		}
		err = tw.WriteHeader(header)
		if err != nil {
			return err
		}
		_, err = io.Copy(tw, file)
		file.Close()
		if err != nil {
			return err
		}
	}
	return nil
}
